package com.gome.ocean.service.scheduler;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import com.gome.ocean.dao.model.datax.ScheduledJobTaskVO;
import com.gome.ocean.service.task.ScheduledJobTask;


/**
 * 调度bean
 * 
 * @author haqiaolong 2016年1月26日 下午1:02:24
 * @since 5.0.0
 */
@Component("schedulerServiceBean")
public class SchedulerServiceBean implements InitializingBean, DisposableBean {

    private static final Logger LOG = LoggerFactory.getLogger(SchedulerServiceBean.class);

    @Autowired
    @Qualifier("scheduler")
    private Scheduler           scheduler;

    @Override
    public void afterPropertiesSet() throws Exception {
        Assert.notNull(scheduler);
        LOG.info("init quartz scheduler success.[{}]", scheduler);
    }

    /**
     * 添加任务
     * 
     * @param jobInfo
     * @param triggerKey:project + jobId
     * @return
     * @throws org.quartz.SchedulerException
     */
    public boolean addJob(ScheduledJobTaskVO scheduledJobTaskVO, Class<? extends ScheduledJobTask> scheduledJobTask)
                                                                                                                    throws SchedulerException {
        String jobName = scheduledJobTaskVO.getJobName(); // 任务名称
        String jobGroup = scheduledJobTaskVO.getJobGroup(); // 组名称
        TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
        JobKey jobKey = new JobKey(jobName, jobGroup);
        // 判断任务是否存在
        if (checkExists(scheduledJobTaskVO)) {
            LOG.info("任务添加失败,任务已存在！请检查！jobInfo:{}", scheduledJobTaskVO);
            return false;
        }

        CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(scheduledJobTaskVO.getCronExpression())
            .withMisfireHandlingInstructionDoNothing();
        CronTrigger cronTrigger = TriggerBuilder.newTrigger()
            .withIdentity(triggerKey)
            .withSchedule(cronScheduleBuilder)
            .build();

        JobDetail jobDetail = JobBuilder.newJob(scheduledJobTask)
            .withIdentity(jobKey)
            .requestRecovery(true)
            .storeDurably(true)
            .build();
        jobDetail.getJobDataMap().put("jobBO", scheduledJobTaskVO);
        scheduler.scheduleJob(jobDetail, cronTrigger);
        LOG.info("任务添加成功! jobDetail:{}, cronTrigger:{}", jobDetail, cronTrigger);
        return true;
    }

    /**
     * 刷新任务
     * 
     * @param jobInfo
     * @return
     * @throws org.quartz.SchedulerException
     */
    public boolean rescheduleJob(ScheduledJobTaskVO scheduledJobTaskVO,
                                 Class<? extends ScheduledJobTask> scheduledJobTask) throws SchedulerException {
        if (checkExists(scheduledJobTaskVO)) {
            removeJob(scheduledJobTaskVO);
        }
        return addJob(scheduledJobTaskVO, scheduledJobTask);
    }

    /**
     * 移除任务
     * 
     * @param jobName
     * @param jobGroup
     * @return
     * @throws org.quartz.SchedulerException
     */
    public boolean removeJob(ScheduledJobTaskVO scheduledJobTaskVO) throws SchedulerException {
        String jobName = scheduledJobTaskVO.getJobName(); // 任务名称
        String jobGroup = scheduledJobTaskVO.getJobGroup(); // 组名称
        JobKey jobKey = new JobKey(jobName, jobGroup);
        TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
        if (!checkExists(scheduledJobTaskVO)) {
            LOG.info("移除终止失败!任务不存在！jobKey:{}", jobKey);
            throw new SchedulerException("任务还没有提交");
        }
        boolean result = false;
        if (scheduler.unscheduleJob(triggerKey)) {
            result = scheduler.deleteJob(jobKey);
        }
        if (result) {
            LOG.info("移除任务成功!triggerKey:{}, result [{}]", triggerKey, result);
        } else {
            LOG.info("移除任务失败!triggerKey:{}, result [{}]", triggerKey, result);
        }
        return result;
    }

    /**
     * 暂停任务
     * 
     * @param jobName
     * @param jobGroup
     * @return
     * @throws org.quartz.SchedulerException
     */
    public boolean pauseJob(ScheduledJobTaskVO scheduledJobTaskVO) throws SchedulerException {
        String jobName = scheduledJobTaskVO.getJobName(); // 任务名称
        String jobGroup = scheduledJobTaskVO.getJobGroup(); // 组名称
        TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
        boolean result = false;
        if (checkExists(scheduledJobTaskVO)) {
            scheduler.pauseTrigger(triggerKey);
            result = true;
            LOG.info("暂停任务成功!triggerKey:{}", triggerKey);
        } else {
            LOG.info("暂停任务失败!triggerKey:{}", triggerKey);
        }
        return result;
    }

    /**
     * 恢复任务
     * 
     * @param jobName
     * @param jobGroup
     * @return
     * @throws org.quartz.SchedulerException
     */
    public boolean resumeJob(ScheduledJobTaskVO scheduledJobTaskVO) throws SchedulerException {
        String jobName = scheduledJobTaskVO.getJobName(); // 任务名称
        String jobGroup = scheduledJobTaskVO.getJobGroup(); // 组名称
        TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
        boolean result = false;
        if (checkExists(scheduledJobTaskVO)) {
            scheduler.resumeTrigger(triggerKey);
            result = true;
            LOG.info("恢复任务成功!triggerKey:{}", triggerKey);
        } else {
            LOG.info("恢复任务失败!triggerKey:{}", triggerKey);
        }
        return result;
    }

    /**
     * 运行任务
     * 
     * @param jobName
     * @param jobGroup
     * @return
     * @throws org.quartz.SchedulerException
     */
    public boolean triggerJob(ScheduledJobTaskVO scheduledJobTaskVO) throws SchedulerException {
        String jobName = scheduledJobTaskVO.getJobName(); // 任务名称
        String jobGroup = scheduledJobTaskVO.getJobGroup(); // 组名称
        JobKey jobKey = new JobKey(jobName, jobGroup);
        boolean result = false;
        if (checkExists(scheduledJobTaskVO)) {
            scheduler.triggerJob(jobKey);
            result = true;
            LOG.info("任务成功执行！jobKey:{}", jobKey);
        } else {
            LOG.info("任务执行失败!任务不存在！jobKey:{}", jobKey);
        }
        return result;
    }

    /**
     * 终止正在执行的任务
     * 
     * @param jobBO
     * @return
     */
    public boolean interrupt(ScheduledJobTaskVO scheduledJobTaskVO) throws SchedulerException {
        String jobName = scheduledJobTaskVO.getJobName(); // 任务名称
        String jobGroup = scheduledJobTaskVO.getJobGroup(); // 组名称
        JobKey jobKey = new JobKey(jobName, jobGroup);
        TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
        if (!checkExists(scheduledJobTaskVO)) {
            LOG.info("任务终止失败!任务不存在！jobKey:{}", jobKey);
            return false;
        }
        boolean result = false;
        if (scheduler.interrupt(jobKey) && scheduler.unscheduleJob(triggerKey)) {
            result = scheduler.deleteJob(jobKey);
        }
        if (result) {
            LOG.info("任务终止成功！jobKey:{}", jobKey);
        } else {
            LOG.info("任务终止失败!jobKey:{}", jobKey);
        }
        return result;
    }

    /**
     * 是否存在
     * 
     * @param jobName
     * @param jobGroup
     * @return
     * @throws org.quartz.SchedulerException
     */
    public boolean checkExists(ScheduledJobTaskVO scheduledJobTaskVO) throws SchedulerException {
        String jobName = scheduledJobTaskVO.getJobName(); // 任务名称
        String jobGroup = scheduledJobTaskVO.getJobGroup(); // 组名称
        TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
        return scheduler.checkExists(triggerKey);
    }

    @Override
    public void destroy() throws Exception {
        if (scheduler != null) {
            scheduler.clear();
        }
    }

}
